package com.mockapi.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mockapi.dto.EventRequest;
import com.mockapi.dto.HttpEventConfig;
import com.mockapi.entity.Event;
import com.mockapi.entity.EventTrigger;
import com.mockapi.mapper.EventMapper;
import com.mockapi.mapper.EventTriggerMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 事件服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EventService {

    private final EventMapper eventMapper;
    private final EventTriggerMapper eventTriggerMapper;
    private final List<EventExecutor> eventExecutors;
    private final ObjectMapper objectMapper;

    /**
     * 分页查询事件
     */
    public Page<Event> getEventPage(int page, int size, String name, String eventType, String triggerType) {
        Page<Event> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Event> wrapper = new LambdaQueryWrapper<>();
        
        if (name != null && !name.trim().isEmpty()) {
            wrapper.like(Event::getName, name);
        }
        if (eventType != null && !eventType.trim().isEmpty()) {
            wrapper.eq(Event::getEventType, eventType);
        }
        if (triggerType != null && !triggerType.trim().isEmpty()) {
            wrapper.eq(Event::getTriggerType, triggerType);
        }
        
        wrapper.orderByDesc(Event::getCreatedAt);
        return eventMapper.selectPage(pageParam, wrapper);
    }

    /**
     * 根据ID获取事件
     */
    public Event getById(Long id) {
        return eventMapper.selectById(id);
    }

    /**
     * 创建事件
     */
    @Transactional
    public Event createEvent(EventRequest request) {
        // 验证事件配置
        validateEventConfig(request.getEventType(), request.getEventConfig());
        
        Event event = new Event();
        event.setName(request.getName());
        event.setDescription(request.getDescription());
        event.setEventType(request.getEventType());
        event.setTriggerType(request.getTriggerType());
        event.setRouteId(request.getRouteId());
        event.setTriggerConfig(request.getTriggerConfig());
        event.setEventConfig(request.getEventConfig());
        event.setEnabled(request.getEnabled());
        event.setRetryCount(request.getRetryCount());
        event.setRetryInterval(request.getRetryInterval());
        event.setTimeout(request.getTimeout());
        
        eventMapper.insert(event);
        return event;
    }

    /**
     * 更新事件
     */
    @Transactional
    public Event updateEvent(Long id, EventRequest request) {
        Event event = eventMapper.selectById(id);
        if (event == null) {
            throw new RuntimeException("事件不存在");
        }
        
        // 验证事件配置
        validateEventConfig(request.getEventType(), request.getEventConfig());
        
        event.setName(request.getName());
        event.setDescription(request.getDescription());
        event.setEventType(request.getEventType());
        event.setTriggerType(request.getTriggerType());
        event.setRouteId(request.getRouteId());
        event.setTriggerConfig(request.getTriggerConfig());
        event.setEventConfig(request.getEventConfig());
        event.setEnabled(request.getEnabled());
        event.setRetryCount(request.getRetryCount());
        event.setRetryInterval(request.getRetryInterval());
        event.setTimeout(request.getTimeout());
        
        eventMapper.updateById(event);
        return event;
    }

    /**
     * 删除事件
     */
    @Transactional
    public void deleteEvent(Long id) {
        eventMapper.deleteById(id);
    }

    /**
     * 启用/禁用事件
     */
    @Transactional
    public void toggleEvent(Long id, boolean enabled) {
        Event event = eventMapper.selectById(id);
        if (event == null) {
            throw new RuntimeException("事件不存在");
        }
        
        event.setEnabled(enabled);
        eventMapper.updateById(event);
    }

    /**
     * 触发事件
     */
    @Transactional
    public EventTrigger triggerEvent(Event event, Map<String, Object> context) {
        if (event == null) {
            throw new RuntimeException("事件不存在");
        }
        
        if (!event.getEnabled()) {
            throw new RuntimeException("事件已禁用");
        }
        
        // 查找对应的执行器
        EventExecutor executor = eventExecutors.stream()
                .filter(e -> e.getSupportedEventType().equals(event.getEventType()))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("不支持的事件类型: " + event.getEventType()));
        
        // 执行事件
        EventTrigger trigger = executor.execute(event, context);
        
        // 保存触发记录
        eventTriggerMapper.insert(trigger);
        
        // 如果执行失败且配置了重试，则进行重试
        if ("FAILED".equals(trigger.getExecutionStatus()) && event.getRetryCount() > 0) {
            retryEvent(event, trigger, context);
        }
        
        return trigger;
    }

    /**
     * 重试事件
     */
    @Transactional
    public void retryEvent(Event event, EventTrigger trigger, Map<String, Object> context) {
        if (trigger.getRetryCount() >= event.getRetryCount()) {
            log.warn("事件重试次数已达上限: eventId={}, retryCount={}", event.getId(), trigger.getRetryCount());
            return;
        }
        
        EventExecutor executor = eventExecutors.stream()
                .filter(e -> e.getSupportedEventType().equals(event.getEventType()))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("不支持的事件类型: " + event.getEventType()));
        
        EventTrigger retryTrigger = executor.retry(event, trigger, context);
        eventTriggerMapper.updateById(retryTrigger);
    }

    /**
     * 获取事件触发记录
     */
    public Page<EventTrigger> getEventTriggerPage(Long eventId, int page, int size) {
        Page<EventTrigger> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<EventTrigger> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EventTrigger::getEventId, eventId);
        wrapper.orderByDesc(EventTrigger::getTriggerTime);
        return eventTriggerMapper.selectPage(pageParam, wrapper);
    }

    /**
     * 根据触发类型获取启用的事件
     */
    public List<Event> getEnabledEventsByTriggerType(Long routeId, String triggerType) {
        LambdaQueryWrapper<Event> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Event::getEnabled, true)
                .eq(Event::getRouteId, routeId)
                .eq(Event::getTriggerType, triggerType)
                .orderByDesc(Event::getCreatedAt);
        return eventMapper.selectList(wrapper);
    }

    /**
     * 手动触发Mock调用后的事件
     */
    public void triggerMockCallEvents(Long routeId, String requestMethod, Map<String, Object> requestData) {
        List<Event> events = getEnabledEventsByTriggerType(routeId, "MOCK_CALL");

        for (Event event : events) {
            try {
                Map<String, Object> context = new HashMap<>();
                context.put("triggerType", "MOCK_CALL");
                context.put("requestData", requestData);
                context.put("routeId", routeId);
                context.put("requestMethod", requestMethod);

                triggerEvent(event, context);
            } catch (Exception e) {
                log.error("触发Mock调用事件失败: eventId={}, error={}", event.getId(), e.getMessage(), e);
            }
        }
    }

    /**
     * 获取事件总数
     */
    public long getCount() {
        return eventMapper.selectCount(null);
    }

    /**
     * 验证事件配置
     */
    private void validateEventConfig(String eventType, String eventConfig) {
        try {
            if ("HTTP".equals(eventType)) {
                objectMapper.readValue(eventConfig, HttpEventConfig.class);
            }
            // 可以在这里添加其他事件类型的验证
        } catch (Exception e) {
            throw new RuntimeException("事件配置格式错误: " + e.getMessage());
        }
    }
} 